/* This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package Controlador;

import Modelo.*;
import Vista.*;

import java.util.*;

import javax.swing.JLabel;

/**
 * Clase que representa a un objeto analizador que se encarga de almacenar las tecnicas seleccionadas y las ejecuta
 * @author Armando Machuca Llorente
 */
public class Analizador {

    /**
     *@
     **/
    private Vector<Plugin> _plugins;
    private Vector _unidades;
    private Calendar _fecha;
    private Vector<Tecnica> _nivel1;
    private Vector<Tecnica> _nivel2;
    private Vector<Tecnica> _nivel3;
    private String analizador; // Nombre de usuario del usuario que analiza
    private String password; //Passprashe para firmar el documento PDF.
    private String p12File; //Fichero para firmar
    private String claveP12;
    private Accionador accionador;
    private int nivel_gravedad;

    /**
     * Constructor de la clase Analizador
     */
    public Analizador() {
        set_fecha(Calendar.getInstance());
        setAccionador(new Accionador());
        _nivel1 = new Vector<Tecnica>(); //El nivel 1 esta dedicado a las busquedas concretas.
        _nivel2 = new Vector<Tecnica>(); //El nivel 2 esta dedicado para la busqueda en todo el registro y busquedas de ficheros dentro de directorios
        _nivel3 = new Vector<Tecnica>(); //El nivel 3 esta dedicado para aquellas tecnicas que recorren todo el disco
    }

    /**
     * Constructor de la clase analizador
     * @param unidades Unidades sobre las que se ejecutara el analisis
     * @param plugins Conjunto de plugins que se usaran para analizar
     */
    public Analizador(Vector unidades, Vector plugins) {
        set_fecha(Calendar.getInstance());
        setAccionador(new Accionador());
        _unidades = unidades;
        _plugins = plugins;
        _nivel1 = new Vector<Tecnica>(); //El nivel 1 esta dedicado a las busquedas concretas.
        _nivel2 = new Vector<Tecnica>(); //El nivel 2 esta dedicado para la busqueda en todo el registro y busquedas de ficheros dentro de directorios
        _nivel3 = new Vector<Tecnica>(); //El nivel 3 esta dedicado para aquellas tecnicas que recorren todo el disco
    }

    /**
     * Metodo que divide las tecnicas en 3 grupos dependiendo de la capacidad de procesamiento requerida
     */
    public void categorizar() {

        //Recorre los plugins e introduce las tecnicas en 3 grupos, dependiendo del tiempo que tardan
        Iterator i = _plugins.iterator();
        while (i.hasNext()) {
            Plugin p = (Plugin) i.next();
            Iterator j = p.getTecnicas().iterator();
            while (j.hasNext()) {
                Tecnica t = (Tecnica) j.next();
                if (t.getValue("tipo").compareTo("barchivo") == 0) {
                    _nivel1.add(t);
                }
                if (t.getValue("tipo").compareTo("breg_ub") == 0) {
                    _nivel1.add(t);
                }
                if (t.getValue("tipo").compareTo("blog") == 0) {
                    _nivel1.add(t);
                }
                if (t.getValue("tipo").compareTo("blog_pd") == 0) {
                    _nivel2.add(t);
                }
                if (t.getValue("tipo").compareTo("breg_all_sec") == 0) {
                    _nivel2.add(t);
                }
                if (t.getValue("tipo").compareTo("breg_all") == 0) {
                    _nivel2.add(t);
                }
                if (t.getValue("tipo").compareTo("barchivo_pname") == 0) {
                    _nivel3.add(t);
                }
                if (t.getValue("tipo").compareTo("blog_all") == 0) {
                    _nivel3.add(t);
                }
            }
        }
    }

    /**
     * Metodo que ejecuta el analisis de las tecnicas de duracion corta
     * @param unidad Especifica la unidad sobre la que se efectuara el analisis
     */
    public void analisisT1(String unidad) { //Analisis de tipo 1. Rapido.
        Iterator i = _nivel1.iterator();
        while (i.hasNext()) {
            Tecnica t = (Tecnica) i.next();       
            t.ejecutar(unidad);     
        }
    }

    /**
     * Metodo que ejecuta el analisis de las tecnicas de duracion media
     * @param unidad Especifica la unidad sobre la que se efectuara el analisis
     */
    public void analisisT2(String unidad) {
        analisisT1(unidad);         
        Iterator i = _nivel2.iterator();
        while (i.hasNext()) {
            Tecnica t = (Tecnica) i.next();
            t.ejecutar(unidad);
        }
    }

    /**
     * Metodo que ejecuta el analisis de las tecnicas de duracion corta
     * @param unidad Especifica la unidad sobre la que se efectuara el analisis
     */
    public void analisisT3(String unidad) { //Analisis de tipo 1. Rapido. Ejecuta tambien analisis 2.
        //Se realiza una optimizacion en este caso para que con la misma pasada busque todos los archivos usando para ello una tecnica temporal
        analisisT2(unidad);      
        Vector v = new Vector();
        Iterator i = _nivel3.iterator();
        TecnicaDisco buscarTodo = new TecnicaDisco("temporal", null);
        while (i.hasNext()) {
            Tecnica t = (Tecnica) i.next();
            
            if (t.getValue("tipo").compareTo("barchivo_pname") == 0) {      
                v.add(t);
            } else {
                t.ejecutar(unidad);
            }
        }

        if (!v.isEmpty()) {
            buscarTodo.bArchivoTodoDisco(unidad, v);
            i = _nivel3.iterator();
            while (i.hasNext()) {
                Tecnica t = (Tecnica) i.next();
            }
        }


        Vector b = new Vector();
        i = _nivel3.iterator();
        TecnicaLog bTodo = new TecnicaLog("temporal", null);
        while (i.hasNext()) {
            Tecnica t = (Tecnica) i.next();
            if (t.getValue("tipo").compareTo("blog_all") == 0) {               
                v.add(t);
            } else {
                t.ejecutar(unidad);
            }
        }

        if (!v.isEmpty()) {
            bTodo.bArchivoTodoDisco(unidad, v);
            i = _nivel3.iterator();
            while (i.hasNext()) {
                Tecnica t = (Tecnica) i.next();
            }
        }     
    }

    /**
     * Metodo que ejecuta el analisis de las tecnicas de duracion larga
     * @param unidad Especifica la unidad sobre la que se efectuara el analisis
     * @param progreso parametro que permite la actualizacion de la interfaz grafica a medida que se ejecutan las acciones mas complejas
     * @param estado parametro que permite la actualizacion de la interfaz grafica a medida que se ejecutan las acciones mas complejas
     */
    public void analisisT3(String unidad, JLabel progreso, JLabel estado) { //Analisis de tipo 1. Rapido. Ejecuta tambien analisis 2.
        //Se realiza una optimizacion en este caso para que con la misma pasada busque todos los archivos usando para ello una tecnica temporal      
        analisisT2(unidad);
        Vector v = new Vector();
        Iterator i = _nivel3.iterator();
        TecnicaDisco buscarTodo = new TecnicaDisco("temporal", null);
        while (i.hasNext()) {
            Tecnica t = (Tecnica) i.next();
            
            if (t.getValue("tipo").compareTo("barchivo_pname") == 0) {
                v.add(t);
            } else {
                t.ejecutar(unidad);
            }
        }

        if (!v.isEmpty()) {
            estado.setText(Idioma.getText("Buscando en todo el disco ficheros"));
            buscarTodo.bArchivoTodoDisco(unidad, v);
            printResultados();
        }


        Vector b = new Vector();
        i = _nivel3.iterator();
        TecnicaLog bTodo = new TecnicaLog("temporal", null);
        while (i.hasNext()) {
            Tecnica t = (Tecnica) i.next();
            if (t.getValue("tipo").compareTo("blog_all") == 0) {
                b.add(t);
            } else {
                t.ejecutar(unidad);
            }
        }

        if (!b.isEmpty()) {
            estado.setText(Idioma.getText("Buscando en todo el disco cadenas"));
            bTodo.bArchivoTodoDisco(unidad, b);
            i = _nivel3.iterator();
            while (i.hasNext()) {
                Tecnica t = (Tecnica) i.next();
            }
        }

    }

    /**
     * Funcion de debug que permite mostrar por la salida estandar los resultados que ha tenido el analisis
     */
    public void printResultados() {
        Iterator i = _plugins.iterator();
        while (i.hasNext()) {
            Plugin p = (Plugin) i.next();
            p.printResults();
        }
    }

    /**
     * Metodo que ejecuta el analisis dependiendo del tipo
     * @param tipoAnalisis Tipo de analisis por gravedad de 1 a 3 menor a mayor
     */
    public void ejecutar(int tipoAnalisis) {
        Iterator i = _unidades.iterator();
        while (i.hasNext()) {
            String unidad = (String) i.next();
            switch (tipoAnalisis) {
                case 1:
                    analisisT1(unidad);
                    break;
                case 2:
                    analisisT2(unidad);
                    break;
                case 3:
                    analisisT3(unidad);
                    break;
            }

        }
        Iterator j = _plugins.iterator();
        while (j.hasNext()) {
            Plugin p = (Plugin) j.next();
            if (p.encontrado()) {
                Date d = new Date();
                Tools.addLogLine(d.toString() + " Located results with plugin " + p.get_name());
            }

        }
    }

    /**
     * Metodo que permite ejecutar pasando por parametro elementos graficos para permitir su actualizacion.
     * @param progreso Elemento grafico que representa el proceso que esta ejecutando la aplicacion al usuario
     * @param estado Elemento grafico que representa el proceso que esta ejecutando la aplicacion al usuario
     * @param tipoAnalisis Tipo de analisis por gravedad de 1 a 3 menor a mayor
     */
    public void ejecutarVisual(int tipoAnalisis, JLabel progreso, JLabel estado) {
        Iterator i = _unidades.iterator();

        while (i.hasNext()) {
            String unidad = (String) i.next();
            progreso.setText(Idioma.getText("Buscando en la unidad") + " " + unidad);
            switch (tipoAnalisis) {
                case 1:
                    analisisT1(unidad);
                    break;
                case 2:
                    analisisT2(unidad);
                    break;
                case 3:
                    
                    analisisT3(unidad, progreso, estado);
                    break;
            }

        }
        Iterator j = _plugins.iterator();
        while (j.hasNext()) {
            Plugin p = (Plugin) j.next();
            if (p.encontrado()) {
                Date d = new Date();
                Tools.addLogLine(d.toString() + " Located results with plugin " + p.get_name());
            }

        }
    }

    /**
     * Elemento que permite cambiar el Nombre del usuario que se encarga de realizar el analisis
     * @param analizador Nombre del usuario que realiza el analisis
     */
    public void setAnalizador(String analizador) {
        this.analizador = analizador;
    }

    /**
     * Metodo get del nombre del analizador
     *@return nombre del analizador
     */
    public String getAnalizador() {
        return analizador;
    }

    /**
     * Metodo set para el password para firmar pdf con el informe
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * Metodo get del password para firmar documentos pdf
     */
    public String getPassword() {
        return password;
    }

    /**
     * Ruta del fichero p12 para firmar documentos pdf
     * @param p12File Ruta del fichero
     */
    public void setP12File(String p12File) {
        this.p12File = p12File;
    }

    /**
     * Metodo get para obtener el nombre del analizador
     */
    public String getP12File() {
        return p12File;
    }

    /**
     * Metodo set para incluir la fecha
     *@param _fecha Fecha a introducir
     */
    public void set_fecha(Calendar _fecha) {
        this._fecha = _fecha;
    }

    /**
     * Metodo get para obtener la fecha
     *
     */
    public Calendar get_fecha() {
        return _fecha;
    }

    /**
     * Metodo set para incluir el conjunto de Plugins a ejecutar
     * @param v Conjunto de plugins
     */
    public void setPlugins(Vector v) {
        _plugins = v;
    }

    /**
     * Metodo get para obtener el conjunto de plugins
     */
    public Vector getPlugins() {
        return _plugins;
    }

    /**
     * Metodo set para intruducir el conjunto de Unidades del analisis
     *@param v Conjunto de unidades
     */
    public void setUnidades(Vector v) {
        _unidades = v;
    }

    /**
     * Metodo get para obtener el conjunto de unidades
     */
    public Vector getUnidades() {
        return _unidades;
    }

    /**
     * Metodo para introducir el nivel de gravedad del analisis
     *@param Nivel_gravedad
     */
    public void setNivel_gravedad(int nivel_gravedad) {
        this.nivel_gravedad = nivel_gravedad;
    }

    /**
     * Metodo para obtener el nivel de gravedad del analisis
     */
    public int getNivel_gravedad() {
        return nivel_gravedad;
    }

    /**
     * Metodo set para introducir el objeto accionador
     * @param accionador Elemento accionador
     */
    public void setAccionador(Accionador accionador) {
        this.accionador = accionador;
    }

    /**
     * Metodo get para obtener el objeto accionador
     * @return Objeto accionador
     */
    public Accionador getAccionador() {
        return accionador;
    }

    /**
     * Metodo set para introducir la clave para firmar los informes
     * @param accionador Elemento accionador
     */
    public void setClaveP12(String claveP12) {
        this.claveP12 = claveP12;
    }

    /**
     * Metodo get para introducir la clave para firmar los informes
     * @return  Clave para firmar
     */
    public String getClaveP12() {
        return claveP12;
    }
}
